﻿using System;
using System.Buffers;
using Letter.IO.Binary;
using Letter.IO.Buf;

namespace Letter.Net.Kcp.Library.KCP;

sealed class BytesBuffer
{
    private static SafeStack<BytesBuffer> pool = new SafeStack<BytesBuffer>();
    
    public static BytesBuffer Allocate()
    {
        if (!pool.TryPop(out var item))
        {
            item = new BytesBuffer();
        }
        
        return item;
    }
    
    private BytesBuffer()
    {
        this.buffer = BufferProvider.Create<byte>();
    }
    
    private IBuffer<byte> buffer;
    
    public int ReadableBytes
    {
        get
        {
            return (int)this.buffer.ReadableLength;
        }
    }
    
    public ReadOnlySequence<byte> GetReadableBuffer()
    {
        return this.buffer.GetReadableSequence();
    }
    
    public void ReaderAdvanceTo(SequencePosition consumed)
    {
        buffer.ReaderAdvanceTo(consumed);
    }

    public void WriteBytes(byte[] bytes, int startIndex, int length)
    {
        if (length <= 0 || startIndex < 0) return;
        
        var buf = new ReadOnlySequence<byte>(bytes, startIndex, length);
        this.WriteBytes(ref buf);
    }

    public void WriteBytes(ref ReadOnlySequence<byte> buf)
    {
        this.buffer.ToBufferWriter().ToBytesWriter().WriteSequence(ref buf);
    }
    
    public void Clear()
    {
        this.buffer.Clear();
    }
    
    public void Dispose()
    {
        this.Clear();
        if (!pool.TryPush(this))
        {
            this.buffer.Release();
        }
    }
}